/*
*	Functions for instruction fetch stage
*	Author : Shyam (shyam2347@gmail.com)
*	Feb 14, 2012 - Valentine's Day :-)
*/

#include <stdio.h>
#include <stdlib.h>
#include "global.h"
#include "parsetrace.c"
#include "queue.h"

#define INS_FETCH 10
int bufferlimit = 0;

// convert a binary string to a decimal number, returns decimal value
int bin2dec(char *bin)   
{
	int b, k, m, n;
  	int len, sum = 0;
  	len = strlen(bin) - 1;
  	int stlen = strlen(bin);
  	for (k = 0; k < stlen; k++) 
  	{
    		n = (bin[k] - '0'); // char to numeric value
    		if (n != 0)
    		{
			sum += (pow(2,(len-k)) * n);
    		}
  	}
  	return sum;
}

unsigned int htoi (const char *ptr)
{
	unsigned int value = 0;
	char ch = *ptr;

	ptr += 2; //skipping 0x
    	while (ch == ' ' || ch == '\t')
        	ch = *(++ptr);
	ch = *ptr;
    	for (;;) {

        if (ch >= '0' && ch <= '9')
            value = (value << 4) + (ch - '0');
        else if (ch >= 'A' && ch <= 'F')
            value = (value << 4) + (ch - 'A' + 10);
        else if (ch >= 'a' && ch <= 'f')
            value = (value << 4) + (ch - 'a' + 10);
        else
            return value;
        ch = *(++ptr);
    }
}

void dec2bin(long long int decimal, char *binary)
{
	int  k = 0, n = 0;
  	long long int  remain;
  	char temp[64];
	memset(temp,'\0',64);
  	do 
  	{
    		remain    = decimal % 2;
   		decimal   = decimal / 2;
    		temp[k++] = remain + '0';
  	} while (decimal > 0);
	while (k != 63)
	{
		temp[k++] = '0';
	}

  	// reverse the spelling
  	while (k >= 0)
    		binary[n++] = temp[--k];
  	binary[n-1] = 0;         // end with NULL
}


int instruction_fetch(FILE *fp, ins *instr)
{
	char *line = malloc(1000 * sizeof(char));
	char *start = line;
	char ch;

	//This looks bad.. I know it, but I will live with you for now..
	//Someone will come to set you right baby.. :)
	while(1)
	{
		//printf("ch : %c\n",ch);
		if( (ch = fgetc(fp)) == EOF)
			return 0;
		if( ch == '\n' )
		{
			*line++ = '\0';
			line = start;
			break;
		}
		if( ch == 0 )
		{
			fseek(fp,100,SEEK_CUR);
			//printf("Bad instruction\n");
			break;
		}
		*line++ = ch;
	}

	int ret;
	if ( (ret=get_readwritefromins(line, instr->rw_address)) != 0)
	{
		instr->rw_check = ret;
		return 2; //It is not an instruction, it is read/write 
	}
	//printf("Line : %s\n",line);
	if( get_insfromins(line, instr->s_instruction) == -1)
		return -1;
	if( get_fromins(line, instr->address, ADDRESS_V) == -1 )
		return -1;
	//if( get_fromins(line, instr->mnemonic, MNEMONIC_V) == -1 )
	//	return -1;
	//printf("Address: %s\t Mnemonic: %s\n",instr->address,instr->mnemonic);
	//printf("Instruction : %s\n",instr->s_instruction);
	if( strlen(instr->address) < 6 )
		printf("Line : %s\n",line);

	char *addr = (char *)malloc(5);
	get_fromins(line,addr,RMAX_V);
	instr->INSC.rmax = atoi(addr);
	free(addr);

	addr = (char *) malloc(5);
	get_fromins(line,addr,WMAX_V);
	instr->INSC.wmax = atoi(addr);
	free(addr);

	addr = (char *) malloc(5);
	get_fromins(line,addr,MEMCOUNT_V);
	instr->INSC.memcount = atoi(addr);
	free(addr);

	free(start);
	
	return 1;
}
